package com.xbongbong.pro.statistics.strategy.chart.type.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.SizeConstant;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.domain.entity.ext.CkPaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.pojo.StatisticBiFormDataEntity;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.BIProductReformEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.helper.ReflectHelper;
import com.xbongbong.paas.toolbox.util.CalendarUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.domain.entity.ChartLimitEntity;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.statistic.constant.ChartConstant;
import com.xbongbong.pro.statistic.constant.RelatedProductConstant;
import com.xbongbong.pro.statistic.enums.ChartLimitTypeEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.help.ChartResultHelp;
import com.xbongbong.pro.statistic.model.ChartLimitModel;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.pojo.SlaveSourcePojo;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartAnalysisVO;
import com.xbongbong.paas.enums.bi.XbbTableRefEnum;
import com.xbongbong.pro.statistics.help.CkResultHelp;
import com.xbongbong.pro.statistics.help.DescribeTableHelper;
import com.xbongbong.pro.statistics.help.DisplayHelper;
import com.xbongbong.pro.statistics.help.InitSqlHelper;
import com.xbongbong.pro.statistics.pojo.dto.ChartAnalysisDTO;
import com.xbongbong.pro.statistics.pojo.dto.GenerateSqlDTO;
import com.xbongbong.pro.statistics.pojo.vo.GenerateSqlVO;
import com.xbongbong.pro.bi.commons.pojo.vo.GroupSqlVO;
import com.xbongbong.pro.statistics.service.CkPaasFormDataService;
import com.xbongbong.pro.statistics.strategy.chart.type.ChartTypeStrategyService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.BiUserTeamEntity;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.BirthdayTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.DistributorAccountEnum;
import com.xbongbong.saas.enums.business.DistributorEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.xbongbong.pro.statistics.help.InitSqlHelper.getIsMaxPermission;

/**
 * 查询表
 *
 * @author xinpeng.jiang
 * @version V1.0
 * @date 2021/5/17 10:00
 * @since V1.0
 */
@Service
public class DataQueryTableStrategyServiceImpl implements ChartTypeStrategyService {

    @Resource
    private CustomerModel customerModel;
    @Resource
    private ChartResultHelp chartResultHelp;
    @Resource
    private InitSqlHelper initSqlHelper;
    @Resource
    private CkPaasFormDataService ckPaasFormDataService;
    @Resource
    private CkResultHelp ckResultHelp;
    @Resource
    private ChartLimitModel chartLimitModel;
    @Resource
    private DisplayHelper displayHelper;
    @Resource
    private DescribeTableHelper describeTableHelper;

    public Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public ChartAnalysisVO chartAnalysis(ChartAnalysisDTO chartAnalysisDTO) throws XbbException {
        ChartAnalysisVO chartAnalysisVO = new ChartAnalysisVO();
        JSONObject result = new JSONObject();
        String corpid = chartAnalysisDTO.getCorpid();
        ChartEntity chartEntity = chartAnalysisDTO.getChartEntity();
        Boolean singleFlag = chartAnalysisDTO.getSingleFlag();
        ChartResultPojo chartResultPojo = chartAnalysisDTO.getChartResultPojo() == null ? new ChartResultPojo() : chartAnalysisDTO.getChartResultPojo();
        PageHelper pageHelper = chartAnalysisDTO.getPageHelper();
        JSONArray tableHeadArr = chartAnalysisDTO.getTableHead();
        Map<JSONObject, FieldAttrPojo> parseAttrMap = chartAnalysisDTO.getParseAttrMap();
        Boolean exportFlag = chartResultPojo.getExportFlag();
        SlaveSourcePojo driverSourcePojo = chartEntity.getDriverSources().toJavaObject(SlaveSourcePojo.class);
        // 单表or多表数据获取
        JSONArray resultArr = chartAnalysisDTO.getResultArray();
        if (!singleFlag) {
            // 关联产品中产品名称和编号需要获取最新的，要先去产品表查一下，再塞回去，麻了
            getNewProduct(corpid, tableHeadArr, driverSourcePojo, resultArr);
        }
        // 自定义pk移动端穿透走查询表逻辑，这里特殊处理
        if (Objects.equals(chartEntity.getChartType(), ChartTypeEnum.PK_CUSTOM.getCode())) {
            if (CollectionsUtil.isEmpty(chartEntity.getDisplayAttr())) {
                chartEntity.setDisplayAttr(chartEntity.getPenetrateAttr());
            }
            Integer businessType = chartEntity.getDriverSources().getInteger(StringConstant.BUSINESS_TYPE);
            for (Object obj : chartEntity.getDisplayAttr()) {
                // 放入businessType
                JSONObject fieldAttrObj = obj instanceof JSONObject ? (JSONObject) obj : null;
                if (fieldAttrObj == null) {
                    continue;
                }
                fieldAttrObj.put(StringConstant.BUSINESS_TYPE, businessType);
                // 比率字段加百分号
                if (FieldAttrEntity.isRate(fieldAttrObj.getString("saasAttr"), fieldAttrObj.getString("numberType"))) {
                    fieldAttrObj.put("percentUsed", 1);
                }
            }
        }
        // 无展示字段直接返回
        if (CollectionUtils.isEmpty(chartEntity.getDisplayAttr())) {
            List<Object> list = new ArrayList<>();
            result.put("customTitle", list);
            result.put("customData", list);
            int rowCount = 0;
            result.put("realRowsCount", rowCount);
            pageHelper.setRowsCount(rowCount);
            chartAnalysisVO.setResult(result);
            return chartAnalysisVO;
        }
 
        //是否展示关联经销商的标识
        boolean linkDistributor = false;
        Map<Long, String> nameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (int i = 0; i < tableHeadArr.size(); i++) {
            JSONObject jsonObject = tableHeadArr.getJSONObject(i);
            if (Objects.equals(jsonObject.getInteger("fieldType"), FieldTypeEnum.LINK_BUSINESS_SINGLE.getType())) {
                linkDistributor = true;
                break;
            }
        }

        try {
            //判断是否为导出情况
            if (exportFlag != null && exportFlag && parseAttrMap != null) {
                // 只存放子表单attr，结构：formId->原attr->新attr
                Map<Long, Map<String, String>> subformAttrMap = new HashMap<>(parseAttrMap.size());
                for (Map.Entry<JSONObject, FieldAttrPojo> fieldAttrPojoEntry : parseAttrMap.entrySet()) {
                    FieldAttrPojo subFieldAttrPojo = fieldAttrPojoEntry.getValue();
                    Integer fieldType = subFieldAttrPojo.getFieldType();
                    if (FieldTypeEnum.isSubFormType(fieldType) && Objects.equals(FieldTypeEnum.SUB_FORM.getType(), fieldType)) {
                        subformAttrMap.computeIfAbsent(subFieldAttrPojo.getFormId(), l -> new HashMap<>()).put(subFieldAttrPojo.getOriginalAttr(), subFieldAttrPojo.getAttr());
                        Integer saasMark = subFieldAttrPojo.getSubForm().getItems().get(0).getSaasMark();
                        ckResultHelp.handleSubFormData4Export(resultArr, chartEntity, subformAttrMap,subFieldAttrPojo.getBusinessType(),saasMark);
                    }
                }
            }
            if (singleFlag) {
                if ((exportFlag == null || !exportFlag) && Objects.equals(XbbRefTypeEnum.DISTRIBUTOR_ACCOUNT.getCode(), driverSourcePojo.getBusinessType()) && linkDistributor) {
                    List<Long> idList = new ArrayList<>();
                    resultArr.forEach(item -> idList.add(((JSONObject) item).getLong(DistributorAccountEnum.DISTRIBUTOR_NAME.getAttr())));
                    List<CustomerEntityExt> customerEntityExts = customerModel.getByKeys(idList, chartEntity.getCorpid());
                    customerEntityExts.forEach(item -> nameMap.put(item.getId(), item.getData().getString(DistributorEnum.NAME.getAttr())));
                    resultArr.forEach(item -> ((JSONObject) item).put(DistributorAccountEnum.DISTRIBUTOR_NAME_LINK_TEXT.getAttr(), nameMap.get(((JSONObject) item).getLong(DistributorAccountEnum.DISTRIBUTOR_NAME.getAttr()))));
                }
                // 渲染查询表
                result = encapsulateTableData(tableHeadArr, resultArr, null, chartEntity, parseAttrMap, chartResultPojo);
            } else {
                // 渲染查询表
                result = encapsulateTableData(tableHeadArr, null, resultArr, chartEntity, parseAttrMap, chartResultPojo);
            }
        } catch (XbbException | IllegalAccessException e) {
            logger.error("解析查询表出错", e);
        }
        // 行数
        int rowCount = pageHelper.getRowsCount();
        result.put("realRowsCount", rowCount);
        if (rowCount > ChartConstant.MAX_SIZE) {
            pageHelper.setRowsCount(ChartConstant.MAX_SIZE);
        }
        chartAnalysisVO.setResult(result);
        return chartAnalysisVO;
    }

    @Override
    public GenerateSqlVO generateSql(GenerateSqlDTO generateSqlDTO) throws XbbException {
        JSONArray tableHead = generateSqlDTO.getTableHead();
        Map<JSONObject, FieldAttrPojo> parseAttrMap = generateSqlDTO.getParseAttrMap();
        ChartEntity chartEntity = generateSqlDTO.getChartEntity();
        ChartResultPojo chartResultPojo = generateSqlDTO.getChartResultPojo();
        boolean isSingle = generateSqlDTO.getSingle();
        GenerateSqlVO generateSqlVO = new GenerateSqlVO();
        StringBuffer stringBuffer = new StringBuffer();
        JSONObject driverSources = chartEntity.getDriverSources();
        // 装配出入库单出库产品和入库产品存一起，但却用了两个businessType，这里转换掉，不然拿不到表名
        if (Objects.equals(driverSources.getOrDefault(ParameterConstant.BUSINESS_TYPE, 0), XbbRefTypeEnum.ASSEMBLE_INPRODUCTS.getCode())) {
            driverSources.put(ParameterConstant.BUSINESS_TYPE, XbbRefTypeEnum.ASSEMBLE_PRODUCT.getCode());
        }
        JSONArray displayAttr = chartEntity.getDisplayAttr();
        if(CollectionsUtil.isEmpty(displayAttr)){
            return generateSqlVO;
        }
        List<ChartFieldAttrPojo> fieldAttrPojoList = JSONArray.parseArray(displayAttr.toJSONString(), ChartFieldAttrPojo.class);
        Map<String, String> sortMap  = displayHelper.getSortMap(chartEntity,chartResultPojo.getSortMap());
//        {"sort": "asc", "field": "num_5&2", "classify": "displayAttr"}
        Map<String, String> sortFieldMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if(sortMap != null && !sortMap.isEmpty()) {
            String field = sortMap.get("field");
            if(StringUtil.isNotEmpty(field)){
                String[] keyArray = field.split("&");
                String attr = keyArray[0];
                String sort = sortMap.get("sort");
                if(StringUtil.isEmpty(sort)){
                    sort = " asc ";
                }
                sortFieldMap.put(attr,sort);
            }
        }

        GroupSqlVO groupSqlVO = new GroupSqlVO();
        //表头
        Pair<List<String>, HashMap<String, Set<String>>> listHashMapPair = initSqlHelper.displayAttrAssemble(fieldAttrPojoList, null, tableHead, parseAttrMap, null,
                chartEntity, isSingle,sortFieldMap,groupSqlVO);
        StringBuffer fields  = new StringBuffer();
//        Map<formId,where 语句>  通过formId找到table  从source里找
        //筛选+查询
        Map<String,StringBuffer>  fliterMap = new HashMap<>(XbbConstant.INITIALCAPACITY);
        boolean isPublicFlag = initSqlHelper.parseConditionIntersection(fliterMap, chartEntity, false);
        if (isPublicFlag){
            fields.append(listHashMapPair.getKey().stream().filter(f->!f.contains(XbbTableRefEnum.CUSTOMER_TEAM.getTableName())).collect(Collectors.joining(",")));
        }else {
            fields.append(listHashMapPair.getKey().stream().collect(Collectors.joining(",")));
        }
        //分页
        PageHelper pageHelper;
        if (chartResultPojo.getPage() != null && chartResultPojo.getPageSize() != null) {
            pageHelper = new PageHelper(chartResultPojo.getPage(), chartResultPojo.getPageSize());
        }else {
            pageHelper = new PageHelper(1,20);
        }
        //固定最大分页
        if (pageHelper.getCurrentPageNum() * pageHelper.getPageSize() > ChartConstant.MAX_SIZE) {
            pageHelper.setCurrentPageNum(ChartConstant.MAX_SIZE / pageHelper.getPageSize());
        }
        Integer page = pageHelper.getCurrentPageNum() == null ? 1 : pageHelper.getCurrentPageNum();
        Integer pageSize =  pageHelper.getPageSize() == null ? 20 :  pageHelper.getPageSize();
        page = page < 1 ? 1 : page;
        int from = (page - 1) * pageSize;
        if (from + pageSize > SizeConstant.PAGE_SIZE) {
            from = 0;
            pageSize = 20;
        }
        pageSize = pageSize == 0 ? 1 : pageSize;

        //构建子查询外层SQL语句的返回字段
        initSqlHelper.buildSubColumnOfCount(groupSqlVO,new ArrayList<>(),Boolean.TRUE);
        String sortField = displayHelper.getAggSortField(sortFieldMap,groupSqlVO);
        boolean isMaxPermission = getIsMaxPermission(chartResultPojo);
        Pair<GroupSqlVO, HashMap<String, Set<String>>> mapPair = new ImmutablePair(groupSqlVO,listHashMapPair.getValue());
        Boolean exportFlag = chartResultPojo.getExportFlag();
        int size = pageSize;
        if(exportFlag!=null && exportFlag){
            ChartLimitEntity chartLimit = chartLimitModel.getByType(ChartLimitTypeEnum.CHART_DATA_EXPORT_LIMIT.getCode(),chartResultPojo.getCorpid());
            if(chartLimit != null){
                if(chartLimit.getLimitNum()!=null && chartLimit.getLimitNum()>0){
                    size = chartLimit.getLimitNum();
                }
            }
        }
        initSqlHelper.tableJoin(mapPair,chartEntity, isSingle, stringBuffer, fields, sortField, fliterMap, size, from,null,isMaxPermission);
        //TODO 
        if(Objects.equals(page,1)){
            Integer rowsCount = getRowCount(stringBuffer);
            pageHelper.setRowsCount(rowsCount);
        }else {
            Integer rowsCount = chartResultPojo.getRowsCount();
            //从前端传回，如果没有再去查
            if(rowsCount == null){
                rowsCount = getRowCount(stringBuffer);
            }
            pageHelper.setRowsCount(rowsCount);
        }
        generateSqlVO.setPageHelper(pageHelper);
        generateSqlVO.setStringBufferSql(stringBuffer);
        return generateSqlVO;
    }

    /**
     *查询表获取总数
     * @param stringBuffer
     * @return
     */
    private Integer getRowCount(StringBuffer stringBuffer) {
        String str = stringBuffer.toString();
        int endIndex ;
        if(str.contains("ORDER BY")){
            endIndex = str.indexOf("ORDER BY");
        }else {
            endIndex = str.indexOf("limit");
        }
        str = str.substring(str.indexOf("from"), endIndex);
        return ckPaasFormDataService.countBySql("select count() " + str);
    }


    /**
     * 渲染查询表
     *
     * @param tableHead     表头数据
     * @param singeEntities 单表查询出来的数据
     * @param mulEntities   多表查询出来的数据
     * @return 整个表的数据
     * @author yuqian
     */
    private JSONObject encapsulateTableData(JSONArray tableHead, JSONArray singeEntities, JSONArray mulEntities,
                                            ChartEntity chartEntity, Map<JSONObject, FieldAttrPojo> parseAttrMap, BaseDTO baseDTO) throws XbbException {
        JSONObject result = new JSONObject();
        JSONArray row = new JSONArray();
        JSONArray rowExplain = new JSONArray();
        List<JSONObject> headList = JSONObject.parseArray(tableHead.toJSONString(), JSONObject.class);
        result.put("customTitle", headList);
        //所有列的值map的集合
        List<List<String>> resultCol = new ArrayList<>();
        List<String> dataIdList = new ArrayList<>();
        JSONObject formIdAttr = chartEntity.getFormIdAttr();
        JSONArray filter = chartEntity.getFilter();
        boolean penetrateFlag = ckResultHelp.getPenetrateFlag(filter);
        JSONObject formIdJson = new JSONObject();
        //单表的图没有初始化formIdAttr，穿透的时候会报错
        if(formIdAttr != null){
            for (String s : formIdAttr.keySet()) {
                JSONObject json = formIdAttr.getJSONObject(s);
                formIdJson.put(s,json.getString(FieldTypeEnum.DATAID.getAlias()));
            }
        }
        for (int i = 0; i < tableHead.size(); i++) {
            JSONObject dataObject = tableHead.getJSONObject(i);
            //兼容解析展现字段方法
            FieldAttrPojo fieldAttrPojo = parseAttrMap.get(dataObject);
            //特殊处理address 字段
            Integer type = fieldAttrPojo.getFieldType();
            String attr = fieldAttrPojo.getAttr();
            //如果是经销商档案的计算方式
            boolean settlementMethod = DistributorEnum.SETTLEMENT_METHOD.getSaasAttr().equals(fieldAttrPojo.getSaasAttr());
            Long formId = fieldAttrPojo.getFormId();
            JSONObject attrMapping = new JSONObject();
            if (formIdAttr != null && formIdAttr.size() > 0) {
                attrMapping = formIdAttr.getJSONObject(formId.toString());
            }
            String key = dataObject.getString("key");
            String[] keySplit = key.split("&");
            List<String> values = new ArrayList<>();
            List<String> keyValues = new ArrayList<>();
            JSONObject tableData = new JSONObject();
            Map<String, String> dataIdToEsId = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionsUtil.isNotEmpty(singeEntities)) {
                for (int j = 0; j < singeEntities.size(); j++) {
                    JSONObject singeEntitiesObj = singeEntities.getJSONObject(j);
                    //ID录入只初始化一次
                    if (i == 0) {
                        dataIdList.add(FastJsonHelper.getStringOrDefault(singeEntitiesObj, ParameterConstant.ID, ""));
                    }
                    if (FieldTypeEnum.ADDRESS.equals(FieldTypeEnum.getFieldTypeEnum(type)) && penetrateFlag) {
                        String addressList = keySplit[0];
                        String[] addressArray = addressList.split("\\.");
//                        attr = addressArray[0];
                        attr = attr.replaceAll("\\.","_") ;
                    }
                    // 判断是否是data内字段，虽然字段已被拉宽，但判断方法还是先用es这个
                    if (!EsUtil.setInData(type)) {
                        //团队特殊处理 需要传dataID 从team中获取团队信息
                        String outData = null;
                        if(EsHelper.isTeamLogicByFieldType(type, fieldAttrPojo.getBusinessType())){
                            outData = processTeamField(chartEntity, type, formId, keyValues, singeEntitiesObj,true);
                        }else {
                            outData =  FastJsonHelper.getStringOrDefault(singeEntitiesObj, attr, "");
                        }
                        values.add(outData);
                    } else {
                        String value = null;
                        //type类型为checkbox_group,且isRedundant为0时 为执行人字段 需传dataId作为value
                        if (Objects.equals(FieldTypeEnum.CHECKBOX_GROUP.getType(), type) && Objects.equals(0, fieldAttrPojo.getIsRedundant()) && !settlementMethod) {
                            value = FastJsonHelper.getStringOrDefault(singeEntitiesObj, ParameterConstant.ID, "");
                        } else {
                            //子表单取值特殊处理
                            if (FieldTypeEnum.isSubFormType(type)) {
                                Object subFormVal = singeEntitiesObj.get(attr);
                                JSONArray subFormJson = subFormVal instanceof JSONArray ? (JSONArray) subFormVal : new JSONArray();
                                value = subFormJson.size() == BasicConstant.ZERO ? "" : subFormJson.toJSONString();
                            }
                            //关联字段 回显
                            else if (Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_BUSINESS_SINGLE.getType()) || Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_BUSINESS_MULTI.getType())
                                    || Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_RECEIVER.getType())) {
                                value = FastJsonHelper.getStringOrDefault(singeEntitiesObj, fieldAttrPojo.getLinkedText(), "");
                            }
                            //客户生日取值特殊处理
                            else if (FieldTypeEnum.BIRTHDAY.getType().equals(type)) {
                                value = describeTableHelper.getBirthday(fieldAttrPojo, singeEntitiesObj, attr);
                            } else {
                                // List Map类型判断
                                if ((singeEntitiesObj.get(attr) instanceof List)) {
                                    List list = singeEntitiesObj.getObject(attr, List.class);
                                    StringBuilder str = new StringBuilder();
                                    if (list != null && list.size() > 0) {
                                        for (Object obj : list) {
                                            str.append(obj).append(",");
                                        }
                                        if (str.length() > 0) {
                                            str.deleteCharAt(str.length() - 1);
                                        }
                                    }
                                    value = str.toString();
                                } else if ((singeEntitiesObj.get(attr) instanceof Map)) {
                                    if (type.equals(FieldTypeEnum.ADDRESS.getType())) {
                                        JSONObject jsonObject = singeEntitiesObj.getJSONObject(attr);
                                        String provinceStr = jsonObject.getString(BusinessConstant.PROVINCE) == null ? "" : jsonObject.getString(BusinessConstant.PROVINCE);
                                        String cityStr = jsonObject.getString(BusinessConstant.CITY) == null ? "" : jsonObject.getString(BusinessConstant.CITY);
                                        String districtStr = jsonObject.getString(BusinessConstant.DISTRICT) == null ? "" : jsonObject.getString(BusinessConstant.DISTRICT);
                                        String addressStr = jsonObject.getString(BusinessConstant.ADDRESS) == null ? "" : jsonObject.getString(BusinessConstant.ADDRESS);
                                        value = provinceStr + cityStr + districtStr + addressStr;
                                    } else {
                                        value = JSONObject.toJSONString(singeEntitiesObj.get(attr));
                                    }
                                } else {
                                    value = FastJsonHelper.getStringOrDefault(singeEntitiesObj, attr, "");
                                    // 特殊处理一下数字类型的值，原因是可能值为int或double类型
                                    if (Objects.equals(FieldTypeEnum.NUM.getType(), type)) {
                                        Double valueDouble = FastJsonHelper.getDoubleOrDefault(singeEntitiesObj, attr, 0D);
                                        if (Objects.nonNull(valueDouble)) {
                                            value = valueDouble.toString();
                                        }
                                    }
                                }
                            }
                        }
                        values.add(value);
                    }
                }
            } else if (CollectionsUtil.isNotEmpty(mulEntities)) {
                for (int j = 0; j < mulEntities.size(); j++) {
                    JSONObject mulEntitiesObj = mulEntities.getJSONObject(j);
                    //ID录入只初始化一次
                    if (i == 0) {
                        JSONObject formIdJsonValue = new JSONObject();
                        for (String s : formIdJson.keySet()) {
                            formIdJsonValue.put(s,FastJsonHelper.getStringOrDefault(mulEntitiesObj, formIdJson.getString(s), ""));
                        }
                        dataIdList.add(formIdJsonValue.toString());
                    }
                    if (FieldTypeEnum.ADDRESS.equals(FieldTypeEnum.getFieldTypeEnum(fieldAttrPojo.getFieldType())) && penetrateFlag) {
                        String addressList = keySplit[0];
                        String[] addressArray = addressList.split("\\.");
//                        attr = addressArray[0];
                        attr = attr.replaceAll("\\.","_") ;
                    }
                    // 判断是否是data内字段，虽然字段已被拉宽，但判断方法还是先用es这个
                    if (!EsUtil.setInData(type)) {
                        String outData;
                        if (EsHelper.isTeamLogicByFieldType(type, fieldAttrPojo.getBusinessType())) {
                            outData = processTeamField(chartEntity, type, formId, keyValues, mulEntitiesObj,false);
//                            processTeamField(values, chartEntity, formId, mulEntitiesObj, Objects.equals(FieldTypeEnum.OWNERID.getType(), type));
                        } else {
                            outData = FastJsonHelper.getStringOrDefault(mulEntitiesObj, keySplit[0], "");
                        }
                        values.add(outData);
                    } else {
                        String value = null;
                        if (Objects.equals(FieldTypeEnum.CHECKBOX_GROUP.getType(), type) && Objects.equals(0, fieldAttrPojo.getIsRedundant())) {
                            value = FastJsonHelper.getStringOrDefault(mulEntitiesObj, FastJsonHelper.getStringOrDefault(attrMapping, StringConstant.DATA_ID, ""), "");
                        } else {
                            Object valueObj = mulEntitiesObj.get(attr);
                            if (valueObj == null) {
                                value = "";
                            } else {
                                //子表单取值特殊处理
                                if (FieldTypeEnum.isSubFormType(type)) {
                                    JSONArray subFormJson = (JSONArray) valueObj;
                                    value = subFormJson.size() == BasicConstant.ZERO ? "" : subFormJson.toJSONString();
                                }
                                //关联字段 回显
                                else if (Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_BUSINESS_SINGLE.getType()) || Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_BUSINESS_MULTI.getType())) {
                                    value = FastJsonHelper.getStringOrDefault(mulEntitiesObj, fieldAttrPojo.getLinkedText(), "");
                                }
                                //客户生日取值特殊处理
                                else if (FieldTypeEnum.BIRTHDAY.getType().equals(type)) {
                                    value = describeTableHelper.getBirthday(fieldAttrPojo, mulEntitiesObj, attr);
                                } else {
                                    if ((valueObj instanceof List)) {
                                        List list = (List) valueObj;
                                        StringBuilder str = new StringBuilder();
                                        if (list.size() > 0) {
                                            for (Object obj : list) {
                                                str.append(obj).append(",");
                                            }
                                            if (str.length() > 0) {
                                                str.deleteCharAt(str.length() - 1);
                                            }
                                        }
                                        value = str.toString();
                                    } else if ((valueObj instanceof Map)) {
                                        if (type.equals(FieldTypeEnum.ADDRESS.getType())) {
                                            JSONObject jsonObject = (JSONObject) valueObj;
                                            String provinceStr = jsonObject.getString(BusinessConstant.PROVINCE) == null ? "" : jsonObject.getString(BusinessConstant.PROVINCE);
                                            String cityStr = jsonObject.getString(BusinessConstant.CITY) == null ? "" : jsonObject.getString(BusinessConstant.CITY);
                                            String districtStr = jsonObject.getString(BusinessConstant.DISTRICT) == null ? "" : jsonObject.getString(BusinessConstant.DISTRICT);
                                            String addressStr = jsonObject.getString(BusinessConstant.ADDRESS) == null ? "" : jsonObject.getString(BusinessConstant.ADDRESS);
                                            value = provinceStr + cityStr + districtStr + addressStr;
                                        } else {
                                            value = JSONObject.toJSONString(valueObj);
                                        }
                                    } else {
                                        value = valueObj.toString();
                                    }
                                }
                            }
                        }
                        values.add(value);
                    }
                }

            }
            Map<String, String> parseDataMap = null;
            if (FieldTypeEnum.isSubFormType(type)) {
                parseDataMap = chartResultHelp.getSubFormMap(fieldAttrPojo, values, chartEntity, baseDTO);
            } else if (Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_BUSINESS_SINGLE.getType()) || Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.LINK_BUSINESS_MULTI.getType())
                    || FieldTypeEnum.BIRTHDAY.getType().equals(type)) {
                parseDataMap = chartResultHelp.assembleDataMap(values);
            } else if (Objects.equals(fieldAttrPojo.getFieldType(), FieldTypeEnum.AREA.getType())) {
                parseDataMap = chartResultHelp.distributorAreaMap(chartEntity.getCorpid());
            } else {
                parseDataMap = valueListAnalysis(fieldAttrPojo, chartEntity.getCorpid(), values, chartEntity, dataIdToEsId, baseDTO);
            }
            tableData.put(key, parseDataMap);
            rowExplain.add(fieldAttrPojo);
            row.add(tableData);
            //做为二位数组 放入查询表的值
            if(CollectionsUtil.isNotEmpty(keyValues)){
                resultCol.add(keyValues);
            }else {
                resultCol.add(values);
            }
        }
        List<JSONObject> dataList = JSONObject.parseArray(row.toJSONString(), JSONObject.class);
        JSONArray queryTableResult = chartResultHelp.queryTableAssemble(resultCol, dataList, rowExplain);
        for (int i = 0; i < queryTableResult.size(); i++) {
            JSONObject jsonObject = queryTableResult.getJSONObject(i);
            jsonObject.put("id", dataIdList.get(i));
        }
        result.put("customData", queryTableResult);
        if (dataList.size() > ChartConstant.MAX_SIZE) {
            result.put("customData", queryTableResult.subList(0, ChartConstant.MAX_SIZE));
        }
        
        return result;
    }
    
    private String processTeamField(ChartEntity chartEntity, Integer type, Long formId, List<String> keyValues, JSONObject singeEntitiesObj, boolean single) {
        String outData;
        String teamKey = null;
        if (FieldTypeEnum.OWNERID.getType().equals(type)) {
            teamKey = XbbConstant.MY_TEAM_MAIN;
        }else if(FieldTypeEnum.COUSERID.getType().equals(type)){
            teamKey = XbbConstant.MY_TEAM;
        }
        int teamIdx = EsUtil.getTeamIdx(chartEntity, formId);
        JSONObject jsonObject = new JSONObject(true);
        JSONArray teamMain = singeEntitiesObj.getJSONArray(teamKey +teamIdx);
        String id;
        if(single){
            id = ParameterConstant.ID;
        }else {
            id = "dataId_"+teamIdx;
        }
        String dataIdKey = FastJsonHelper.getStringOrDefault(singeEntitiesObj, id, "");
        jsonObject.put(dataIdKey,teamMain);
        outData = jsonObject.toJSONString();
        keyValues.add(dataIdKey);
        return outData;
    }

    /**
     * 处理计算字段
     *
     * @param fieldAttrPojo
     * @param entityExt
     * @param value
     * @return
     */
    public static String getComputedValue(FieldAttrPojo fieldAttrPojo, JSONObject entityExt, String value) {
        String tempAttr = fieldAttrPojo.getAttr();
        //根据当前计算字段的attr决定调用哪个
        Object tempObject = null;
        if (Objects.nonNull(tempObject)) {
            double tempDouble = Double.parseDouble(tempObject.toString());
            value = String.format("%.2f", tempDouble);
        }
        return value;
    }


   

    private String getBirthday(FieldAttrPojo fieldAttrPojo, StatisticBiFormDataEntity statisticPaasFormDataEsEntity, String attr) {
        String value = "";
        Object dataValueObj = ReflectHelper.valueGet(statisticPaasFormDataEsEntity, attr);
        String dataValue = dataValueObj == null ? null : dataValueObj.toString();
        Object birthTypeObj = ReflectHelper.valueGet(statisticPaasFormDataEsEntity, fieldAttrPojo.getLinkedText());
        Integer birthType = birthTypeObj == null ? null : birthTypeObj instanceof Double ? ((Double) birthTypeObj).intValue() : (Integer) birthTypeObj;
        //判断是公历生日或农历生日
        if (Objects.equals(birthType, BirthdayTypeEnum.BIRTHDAY.getValue())) {
            value = dataValue;
        } else {
            if (dataValue != null) {
                value = CalendarUtil.lunar2Str(dataValue);
            }
        }
        return value;
    }

    /**
     * 处理多表情况下的团队字段回显
     *
     * @param values                        回显字段集合
     * @param chartEntity                   图表信息
     * @param formId                        表单模板ID
     * @param mulEntitiesObj ES查询结果
     * @param isMainTeamType                是否为负责人
     * @author zhouwq
     * @date 2020/5/14 15:56
     */
    private void processTeamField(List<String> values, ChartEntity chartEntity, Long formId, JSONObject mulEntitiesObj, boolean isMainTeamType) {
        int teamIdx = EsUtil.getTeamIdx(chartEntity, formId);
        String teamAttr = "myTeam_" + teamIdx;
        Object outData = mulEntitiesObj.get(teamAttr);
        Integer isMain = isMainTeamType ? 1 : 0;
        if (outData == null) {
            values.add("");
            return;
        }
        JSONArray teamArray = (JSONArray) outData;
        StringBuilder value = new StringBuilder();
        for (int y = 0; y < teamArray.size(); y++) {
            JSONObject teamObj = teamArray.getJSONObject(y);
            BiUserTeamEntity biUserTeamEntity = JSON.parseObject(teamObj.toJSONString(), BiUserTeamEntity.class);
            if (Objects.equals(biUserTeamEntity.getIsMain(), isMain) && Objects.equals(biUserTeamEntity.getDel(), DelEnum.NORMAL.getDel())) {
                value.append(biUserTeamEntity.getUserName()).append(StringConstant.COMMA);
            }
        }
        if (value.length() == 0) {
            values.add("");
        } else {
            values.add(value.substring(0, value.length() - 1));
        }
    }

    private Map<String, String> valueListAnalysis(FieldAttrPojo field, String corpId, List<String> values, ChartEntity chartEntity, Map<String, String> dataIdToEsId, BaseDTO baseDTO) throws XbbException{
        return ckResultHelp.valueListAnalysis(field, corpId, values, chartEntity, false, dataIdToEsId, false, baseDTO,null);
    }
    
    /**
     * 获取关联产品最新的名称和编号
     * @param corpid
     * @param tableHeadArr 表头
     * @param driverSourcePojo 主表
     * @param resultArr 数据结果
     * @throws XbbException
     * @author xinpeng.jiang
     * @date 2022/1/25 19:07
     * @version 1.0
     */
    private void getNewProduct(String corpid, JSONArray tableHeadArr, SlaveSourcePojo driverSourcePojo, JSONArray resultArr) {
        if (!BIProductReformEnum.getProductSubBusList().contains(driverSourcePojo.getBusinessType()) || CollectionsUtil.isEmpty(resultArr)) {
            return;
        }
        StringBuilder column = new StringBuilder(ParameterConstant.ID);
        boolean isSelectName = false;
        String productNameAttr = "";
        boolean isSelectNo = false;
        String productNoAttr = "";
        // 判断是否选了产品名称或者产品编号
        for (int i = 0; i < tableHeadArr.size(); i++) {
            JSONObject tableHead = tableHeadArr.getJSONObject(i);
            if (!BIProductReformEnum.getProductSubBusList().contains(tableHead.getInteger(StringConstant.BUSINESS_TYPE))) {
                continue;
            }
            if (Objects.equals(SelectProductEnum.PRODUCT.getAttr(), tableHead.getString("originAttr"))) {
                // 选名称
                isSelectName = true;
                productNameAttr = tableHead.getString("attr");
                column.append(XbbConstant.SQL_COMMA).append(XbbConstant.JSON_EXTRACT).append(XbbConstant.L_P).append(XbbTableRefEnum.PRODUCT.getTableName()).append(XbbConstant.POINT).append(XbbConstant.DATA).append(XbbConstant.SQL_COMMA).append(InitSqlHelper.format4Text(ProductEnum.NAME.getAttr())).append(MessageFormat.format("{0}{1}{2}{3}", XbbConstant.SQL_COMMA, XbbConstant.SINGLE_QUOTES, XbbConstant.STRING_CONSTANT, XbbConstant.SINGLE_QUOTES)).append(XbbConstant.R_P).append(" AS productName");
            } else if (Objects.equals(RelatedProductConstant.COMMON_PRODUCT_SERIAL_NO_ATTR, tableHead.getString("originAttr"))) {
                // 选编号
                isSelectNo = true;
                productNoAttr = tableHead.getString("attr");
                column.append(XbbConstant.SQL_COMMA).append(XbbConstant.JSON_EXTRACT).append(XbbConstant.L_P).append(XbbTableRefEnum.PRODUCT.getTableName()).append(XbbConstant.POINT).append(XbbConstant.DATA).append(XbbConstant.SQL_COMMA).append(InitSqlHelper.format4Text(ProductEnum.PRODUCT_NO.getAttr())).append(MessageFormat.format("{0}{1}{2}{3}", XbbConstant.SQL_COMMA, XbbConstant.SINGLE_QUOTES, XbbConstant.STRING_CONSTANT, XbbConstant.SINGLE_QUOTES)).append(XbbConstant.R_P).append(" AS productNo");
            }
            // 都选了就不用循环了
            if (isSelectName && isSelectNo) {
                break;
            }
        }
        // 选了其中一个就要去查库
        if (isSelectName || isSelectNo) {
            // 获取产品id
            List<Long> productIdList = new ArrayList<>();
            for (int i = 0; i < resultArr.size(); i++) {
                JSONObject resultObj = resultArr.getJSONObject(i);
                productIdList.add(resultObj.getLong(RelatedProductConstant.PRODUCT_ID));
            }
            // 查库
            StringBuilder sql = new StringBuilder();
            sql.append("select ").append(column).append(" from ").append(XbbTableRefEnum.PRODUCT.getTableName())
                    .append(" where ").append(ParameterConstant.CORPID).append(XbbConstant.EQUAL).append(InitSqlHelper.format4Text(corpid))
                    .append(XbbConstant.AND).append(ParameterConstant.ID).append(" in ").append(productIdList)
                    .append(XbbConstant.AND).append(ParameterConstant.DEL).append(XbbConstant.EQUAL).append(DelEnum.NORMAL.getDel());
            List<CkPaasFormDataEntityExt> productResultList = ckPaasFormDataService.findEntitysBySql(sql.toString());
            Map<Long, CkPaasFormDataEntityExt> productResultMap = productResultList.stream().collect(Collectors.toMap(CkPaasFormDataEntityExt::getId, p -> p, (k1, k2) -> k1));
            // 塞回去
            if (CollectionsUtil.isNotEmpty(productResultList)) {
                for (int i = 0; i < resultArr.size(); i++) {
                    JSONObject resultObj = resultArr.getJSONObject(i);
                    CkPaasFormDataEntityExt ckPaasFormDataEntityExt = productResultMap.getOrDefault(resultObj.getLong(RelatedProductConstant.PRODUCT_ID), null);
                    if (Objects.nonNull(ckPaasFormDataEntityExt)) {
                        if (isSelectName) {
                            resultObj.put(productNameAttr, ckPaasFormDataEntityExt.getProductName());
                        }
                        if (isSelectNo) {
                            resultObj.put(productNoAttr, ckPaasFormDataEntityExt.getProductNo());
                        }
                    }
                }
            }
        }
    }
}
